Skip to content

Add PHPStan extension banning panicking monad unwraps#19

Merged
erikgaal merged 2 commits into
mainfrom
phpstan-extension
Jun 1, 2026
Merged

Add PHPStan extension banning panicking monad unwraps#19
erikgaal merged 2 commits into
mainfrom
phpstan-extension

Conversation

@erikgaal

@erikgaal erikgaal commented Jun 1, 2026

Copy link
Copy Markdown
Member

What

Ships a PHPStan extension (a RestrictedMethodUsageExtension) that flags the panicking "escape-hatch" unwrap methods on Result and Option, nudging callers toward explicit handling.

It reports two situations:

  • May panic — value typed as the abstract base:
    • Result::unwrap() (throws on Err), Result::unwrapErr() (throws on Ok)
    • Option::unwrap() (throws on None)
  • Always panics — value narrowed to the failing variant:
    • Err::unwrap(), Ok::unwrapErr(), None::unwrap()

Messages steer toward match(), expect()/expectErr(), unwrapOr()/unwrapOrElse(), and mapOrElse() (the Option message deliberately omits match(), which Option doesn't have).

How it's wired

  • extension.neon registers the service under the phpstan.restrictedMethodUsageExtension tag.
  • composer.json gains extra.phpstan.includes, so consumers using phpstan/extension-installer pick it up automatically.
  • The extension lives in src/PHPStan/ (namespace Superscript\Monads\PHPStan) so it's production-autoloaded for consumers.

The library's own analysis is unaffected: it doesn't depend on extension-installer, so its internal unwrap() usage (e.g. Option::collect()) isn't flagged.

Tests

tests/PHPStan/NoPanickingMonadUnwrapExtensionTest.php uses PHPStan's RuleTestCase with the built-in RestrictedMethodUsageRule against a fixture. The exhaustive assertion verifies all six banned calls are flagged with their exact messages, and that safe calls (Ok::unwrap, Some::unwrap, match, unwrapOr) are not flagged.

Verification

  • vendor/bin/pest tests/PHPStan — passes
  • vendor/bin/phpstan analyse — library self-analysis stays clean
  • composer validate — valid

🤖 Generated with Claude Code

Ships a RestrictedMethodUsageExtension that flags the panicking
escape-hatch methods on Result and Option:

- Result::unwrap()/unwrapErr() and Option::unwrap() (may panic)
- Err::unwrap(), Ok::unwrapErr(), None::unwrap() (always panic when
  the type is narrowed to the failing variant)

Messages steer callers toward match(), expect()/expectErr(),
unwrapOr()/unwrapOrElse() and mapOrElse(). Registered via
extension.neon and composer's extra.phpstan.includes so consumers
using phpstan/extension-installer pick it up automatically; the
library's own analysis is unaffected.

Includes a RuleTestCase covering every banned call and asserting safe
calls are not flagged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@erikgaal erikgaal requested a review from robertvansteen June 1, 2026 14:29
@erikgaal erikgaal marked this pull request as ready for review June 1, 2026 14:29
After isOk()/isErr() (Result) or isSome() (Option), the value is
narrowed to the safe variant, so unwrap()/unwrapErr() must not be
flagged. The exhaustive RuleTestCase assertion enforces no errors are
emitted for these guarded calls.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@erikgaal erikgaal merged commit 0ef66f3 into main Jun 1, 2026
4 checks passed
@erikgaal erikgaal deleted the phpstan-extension branch June 1, 2026 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants